package 基础语法.反射;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

public class 反射获取成员方法 {
    public static void main(String[] args) throws Exception {
        // 获取class子节吗文件的对象
        Class mClass = Class.forName("基础语法.反射.MyClass");// 可以不用加<String>,免得要强制转换

        // 获取全部公开的方法，方式和获取全部公开的属性类似
        Method[] me = mClass.getMethods();// 也会获取父类的public方法
        for (Method mei : me) {
            System.out.println(mei);
        }
        System.out.println();

        // 获取全部的方法，方式和获取全部的属性类似
        Method[] med = mClass.getDeclaredMethods();// 不会获取父类的public方法，注意toString重写后可获取到
        for (Method mei : med) {
            System.out.println(mei);
        }

        Method meS = mClass.getMethod("setB", int.class);// 获取单个公开的方法
        System.out.println(meS);
        Method meSp = mClass.getDeclaredMethod("setC", int.class);// 获取单个private的方法

        System.out.println(meSp);

        // 获取方法的权限修饰符
        System.out.println(meSp.getModifiers());
        // 获取方法的名字
        System.out.println(meSp.getName());

        // 获取 方法的 参数
        Parameter[] ps = meSp.getParameters();
        for (Parameter pi : ps) {
            System.out.println(pi);
        }

        // 获取方法抛出的异常
        Class[] exc = meSp.getExceptionTypes();
        for (Class exci : exc) {
            System.out.println(exci);
        }

        // 获取方法上的所有注解：
        Annotation[] as = meSp.getAnnotations();
        for (Annotation asi : as) {
            if (asi.getClass() == InnerMyClass.class) {// 为什么不行？因为Annotation的字节码文件不是InnerMyClass
                // 应该用asi.annotationType() == InnerMyClass.class

                /**
                 * 注解本质上是一个 接口（interface）,Java 编译器会把它编译成一个 接口，这个接口隐式继承自 java.lang.annotation.Annotation。
                 * InnerMyClass的 定义在 JVM 看来类似于：
                 * public interface InnerMyClass extends java.lang.annotation.Annotation 
                 * 
                */
                InnerMyClass ic = (InnerMyClass) asi;//强转
                System.out.println("InnerMyClass.class:" + asi);
            } else
                System.out.println(asi);
        }
        // 获取方法上的单个注解
        if (meSp.isAnnotationPresent(InnerMyClass.class)) {
            InnerMyClass ass = meSp.getAnnotation(InnerMyClass.class);// 返回值是Annotation类型

            System.out.println(ass);
            System.out.println(ass.someClass());
            System.out.println(ass.someInt());
            System.out.println(ass.otherAnno());
        }
        MyClass myClass = new MyClass();
        meSp.setAccessible(true);// meSp是private的，先取消
        Object rt = meSp.invoke(myClass, 1911991919);// 第二个参数是setC的值，若setC没有返回值，可以不定义Object

        System.out.println(rt);
        System.out.println(myClass);

    }

}
